/*
*
* 一个用作搭建三维环境的类 world.js
*
* Daniel
* 2018.03.02
* */
define(function(){
    var World = function(){
    
        //--公有属性--//
        
        this.numberData = 1;
        this.canvas = false;
        this.octree = true;
        this.webgl = true;
        
        this.scene = {};
        this.sceneHelper = {};
        this.container = {};
        this.stopRotate = {};
        
        this.camera = {};
        this.viewCamera = {};
        this.ortCamera = {};
        this.cameraId = {};
       
        
        this.renderer = {};             //webgl_render
        this.canvasRenderer = {};       //canvas_render
        
        //相机管理器
        this.cameraGroup = [];
        this.cameraArrays = [];
        this.cameraList = {};
        
        //灯管管理器
        this.lightGroup = [];
        this.lightList = {};
    
        //模型管理器
        this.modelGroup = {};                 //模型分组
        this.childrenGroup = {};              //子模型分组
        
        this.modelArray = [];                 //模型总和
        this.modelGroupArray = [];            //模型组总和
        
        this.modelShell = [];            //模型外壳总和
        
        
        this.textureArray= [];               //纹理总和
        
        this.modelIdIndex = [];             //模型id索引
        this.modelNameIndex = [];           //模型名称索引
        
        this.modelBoderArray = [];          //边框收集器
        this.modelBoderGroup = {};          //边框容器
        this.contArray = {
            pickArray: [],
            oldColor: [],
            id: [],
            time: null,
            otherData: [],
            oneArray:[],
            oneOldColor:[]
        
        };              //高亮模型容器
        
        this.focusModel = {};                //已拾取的模型
        this.colorGroup = {};               //颜色管理器
       
        
        //渲染队列
        this.updateFun = [];
            
            //添加渲染插件
        this.updateAdd = function(fun){
            this.updateFun.push(fun);
        };
            //移除渲染插件
        this.updateRemove = function(value){
            this.updateFun.slice(value);
        };
        
    };
    
    //公共方法
    
    //World初始化
    World.prototype.init = function(DivId){
        var container = document.getElementById(DivId);
        if(container == undefined)return function(){};
        var scope = this;
        this.scene = new THREE.Scene();
        this.scene.background = new THREE.Color(0x313E48);
        this.sceneHelper = new THREE.Scene();
        this.container = container;
        this.changeSize = this.container.parentElement.parentNode;
        this.width = this.container.parentElement.parentNode.clientWidth;
        this.height = this.container.parentElement.parentNode.clientHeight;
        return function(parameters){
            parameters == undefined ? parameters = {} : parameters;
            var orbt = parameters.OrbitCamera || {    //轨道相机
                name: "camera",
                view: 45,                           //视场角度
                position: new THREE.Vector3( 200, 20, 200 ),     //相机位置
                //position: new THREE.Vector3( -1079.4739226622023, 0,0    ),     //相机位置
                area: 200,              //可视范围
                lookat: new THREE.Vector3(0,0,0),              //聚焦中心点
                id: 1
            };
            var free = parameters.freeCamera || {    //自由相机
                name: "freecamera",
                view: 45,                           //视场角度
                position: new THREE.Vector3(0,10,0),     //相机位置
                area: 200,              //可视范围
                lookat: new THREE.Vector3(),              //聚焦中心点
                id: 2
            };
            var ort = parameters.ortCamera || {    //自由相机
                name: "ortCamera",
                width: 1000,                           //视场角度
                height: 1000,                           //视场角度
                position: new THREE.Vector3(0,0,1000),     //相机位置
                area: 2000,              //可视范围
                lookat: new THREE.Vector3(),              //聚焦中心点
                id: 3,
                flag: "ort"
            };
            var light = parameters.AmbientLight ||{
                    name: "AmbientLight",
                    type: "AmbientLight",
                    intensity: 1,         //光线强度
                    color: 0x404040,        //光线颜色
                    position: new THREE.Vector3(0,0,0),        //光线颜色
                };//添加环境光
            var direction = parameters.DirectionalLight || {
                    name: "DirectionalLight",
                    type: "DirectionalLight",
                    intensity: 1,         //光线强度
                    color: 0xffffff,        //光线颜色
                    castShadow:false,        //阴影
                    position: new THREE.Vector3(200,300,200)
        
                };//平行光
            var scene = scope.scene;
            var sceneHelper = scope.sceneHelper;
            
            
            //创建Camera
            scope.camera = scope.addCamera(orbt, scene);
            scope.viewCamera = scope.addCamera(free, scene);
            scope.ortCamera = scope.addCamera(ort, scene);
    
            //创建环境光
            scope.ambientLight = scope.addLight(light, scene);
            scope.directionalLight= scope.addLight(direction);
    
            //创建相机
            scope.camera.add(scope.directionalLight);
            scope.camera.add(scope.directionalLight.target);
    
            //相机数组
            scope.cameraArrays.push(scope.camera, scope.viewCamera);
    
            //创建webgl渲染器
            scope.renderer = scope.addRender({ container: container });
            
            //创建canvas渲染器
            scope.canvasRenderer = scope.addCanvasRender({ container: container });
            
            //添加渲染物
            scope.updateFun.push(
                function(){
                    sceneHelper.updateMatrixWorld();
                    scene.updateMatrixWorld();
                    if(scope.webgl){
                        scope.renderer.render(scene, scope.cameraCoupling(scope.numberData));
                       if ( THREE.RaytracingRenderer && scope.renderer instanceof THREE.RaytracingRenderer === false ) {
                            scope.renderer.render( sceneHelper, scope.cameraCoupling(scope.numberData) );             //矢量图形渲染器
                        }
                    }
                },
                function(){if(scope.canvas){scope.canvasRenderer.render(scene,scope.cameraCoupling(scope.numberData));scope.canvas=false}}//                function(){if(scope.octree){scope.Octree.update()}}
            );
            
            window.addEventListener('resize',  onWindowResize, false);
            scope.animation = animation;
            
            //场景自适应
            function onWindowResize(){
                scope.upDateCamera(scope.cameraArrays);
                var widths = scope.container.parentElement.parentNode.clientWidth;
                var heights = scope.container.parentElement.parentNode.clientHeight;
                scope.renderer.setSize(widths, heights);
                scope.canvasRenderer && scope.canvasRenderer.setSize(widths, heights);
            }
    
            //动态渲染
            function animation(){
                requestAnimationFrame(animation);
                scope.render();
            }
        };
    };
    
    //新增场景
    World.prototype.addScene = function (parameters){
        //场景的基本信息
        var scene = new THREE.Scene();
        
        //场景管理器
        return scene;
    };
    
    //新增相机
    World.prototype.addCamera = function (parameters, scene){
        var scenes = scene;
        var view = parameters.view;
        var width = parameters.width ;
        var height = parameters.height;
        var area = parameters.area;
        var name = parameters.name;
        var x = parameters.position.x;
        var y = parameters.position.y;
        var z = parameters.position.z;
        var id = parameters.id;
        var flag = parameters.flag;
        var camera,node= this.container.parentElement.parentNode,w=node.clientWidth,h=node.clientHeight;
        var aspect = w/h;
        flag !== undefined ? camera = new THREE.OrthographicCamera(width * aspect/ - 2, width * aspect/ 2, height / 2, height / - 2, 1, area) : camera= new THREE.PerspectiveCamera(view, aspect, 1, area);
        // camera.setViewOffset( fullWidth, fullHeight, viewX, viewY, viewWidth, viewHeight );
        camera.name = name;
        camera.pickEnable = true;
        camera.position.set(x, y, z);
        camera.lookAt(parameters.lookat);
        camera.looks = parameters.lookat;
        
        scenes.add(camera);
        this.cameraGroup.push(camera);
        this.cameraList["" + name + ""] = camera;
        this.cameraId["camera"+id] = camera;
        return camera;
    };
    
    //新增灯光
    World.prototype.addLight = function (parameters, scene){
        //获取参数；
        var light;
        var name = parameters.name;
        var type = parameters.type;
        var color = parameters.color;
        var distance = parameters.distance;
        var angle = parameters.angle;
        var penumbra = parameters.penumbra;
        var decay = parameters.decay;
        var intensity = parameters.intensity;
        var shadow = parameters.shadow;
        var castShadow = parameters.castShadow;
        var position = parameters.position;
        
        //灯光分类
        if (type == "AmbientLight")
        {
            light = new THREE.AmbientLight(color, intensity);
        }
        else
        {
            if (type == "SpotLight")
            {
                light = new THREE.SpotLight(color, intensity, distance, angle, penumbra, decay);
                if (shadow !== undefined)
                {
                    light.castShadow = shadow.castShadow;
                    light.shadow.mapSize.width = shadow.mapSize.width;
                    light.shadow.mapSize.height = shadow.mapSize.height;
                    light.shadow.camera.near = shadow.camera.near;
                    light.shadow.camera.far = shadow.camera.far;
                    
                    var sphereGeometry = new THREE.SphereBufferGeometry(5, 32, 32);
                    var sphereMaterial = new THREE.MeshStandardMaterial({ color: 0xff0000 });
                    var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
                    sphere.castShadow = true;
                    sphere.receiveShadow = false;
                    scene.add(sphere);
                }
            }
            else
            {
                if (type == "PointLight")
                {
                    light = new THREE.PointLight(color, intensity, distance);
                } else
                {
                    if (type == "DirectionalLight")
                        light = new THREE.DirectionalLight(color);
                }
            }
        }
        light.position.set(position.x, position.y, position.z).normalize();
        light.name = name;
        light.castShadow = true;
        if (scene) {
            this.lightGroup.push(light);
            this.lightList["" + name + ""] = light;
            scene.add(light);
        }
        return light;
    };
    
    //新增webgl渲染器
    World.prototype.addRender = function (parameters){
        var elements = parameters.container,node= parameters.container.parentElement.parentNode;
        var renderer, w= node.clientWidth, h= node.clientHeight;
        renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
        renderer.autoClear = false;
        renderer.autoUpdateScene = false;
        renderer.setSize(w, h);
        renderer.setPixelRatio(window.devicePixelRatio);
        elements.appendChild(renderer.domElement);
        this.renderer = renderer;
        return renderer;
    };
    
    //新增canvas渲染器
    World.prototype.addCanvasRender = function (parameters) {
        var elements = parameters.container,node= parameters.container.parentElement.parentNode;
        var renderer, w = node.clientWidth, h = node.clientHeight;
        renderer = new THREE.CanvasRenderer();
        renderer.setClearColor(parameters.color, 1);
        // renderer.setSize(window.innerWidth, window.innerHeight);                 ////适应整个window
        renderer.setSize(w, h);
        renderer.setPixelRatio(window.devicePixelRatio);
        elements && elements.appendChild(renderer.domElement);
        renderer.domElement.style.display = "none";
        this.canvasRenderer = renderer;
        return renderer;
    };
    
    //更新相机视角
    World.prototype.upDateCamera =  function(cameraArray){
        var camera;
        var len = cameraArray.length;
        var i = 0;
        for (; i < len; i++)
        {
            camera = cameraArray[i];
            camera.aspect = this.changeSize.clientWidth / this.changeSize.clientHeight;
            camera.updateProjectionMatrix();
        }
    };
    
    //相机离合器
    World.prototype.cameraCoupling = function(num){
        var camera = this.cameraId["camera"+num+""];
        if(camera == undefined)return this.cameraId["camera1"];
           return camera;
        
    };
    
    //更新队列
    World.prototype.update = function () {
        var i = 0;
        var len = this.updateFun.length;
        for(;i<len;i++){
            this.updateFun[i]();
        }
    };
    
    //添加模型外边框
    World.prototype.addBorder = function(object,color){
        var box = new THREE.BoxHelper( object, color );
        var points = box.geometry.attributes.position.array;
        var vectorArray = [];
        var groups = new THREE.Group();
        groups.name = "borders";
        var material = new THREE.LineBasicMaterial({
            color: color         //mesh.material.color
        });
        var len = points.length;
        for(var i = 0; i<len;i+=3){
            var vectors = new THREE.Vector3(points[i],points[i+1],points[i+2]);
            vectorArray.push(vectors);
        }
        var vectorArrays = [
            [vectorArray[0], vectorArray[1]],
            [vectorArray[0], vectorArray[3]],
            [vectorArray[0], vectorArray[4]],
            [vectorArray[2], vectorArray[1]],
            [vectorArray[2], vectorArray[3]],
            [vectorArray[2], vectorArray[6]],
            [vectorArray[5], vectorArray[1]],
            [vectorArray[5], vectorArray[4]],
            [vectorArray[5], vectorArray[6]],
            [vectorArray[7], vectorArray[4]],
            [vectorArray[7], vectorArray[3]],
            [vectorArray[7], vectorArray[6]]
        ];
        var length = vectorArrays.length;
        for(var j = 0; j <length; j++){
            var geom = new THREE.Geometry();
            var end = vectorArrays[j][1];
            var start = vectorArrays[j][0];
            var X = Number(end.x - start.x);
            var Y = Number(end.y - start.y);
            var Z = Number(end.z - start.z);
            var maxLength = Math.max(Math.max(Math.abs(X),Math.abs(Y)),Math.abs(Z));
            var segments = maxLength/0.5;
            var deltX = X/segments;
            var deltY = Y/segments;
            var deltZ = Z/segments;
            var newPoint = new THREE.Vector3(vectorArrays[j][0].x,vectorArrays[j][0].y,vectorArrays[j][0].z);
            var long = Math.ceil(segments)+1;
            for( var k = 0; k < long; k++){
                if(k!=0){
                    if(k<segments){
                        newPoint.x += deltX;
                        newPoint.y += deltY;
                        newPoint.z += deltZ;
                        geom.vertices.push(newPoint.clone());
                    }else{
                        geom.vertices.push(end);
                    }
                }else{
                    geom.vertices.push(start);
                }
            }
            var borderlines = new THREE.LineSegments(geom, material);
            groups.add(borderlines);
        }
        this.modelBoderArray.push(groups);
        this.scene.add( groups );
    };
    
    //移除模型外边框
    World.prototype.removeBorder = function (){
        var length = this.modelBoderArray.length;
        if(length == 0)return;
        var LineGroup = this.modelBoderArray;
        for(var i = 0; i < length; i++){
            var line = LineGroup[i];
            this.scene.remove(line);
        }
    };
    
    //模型高亮
    World.prototype.showModelData = function (params){
        var contArray = this.contArray;
        var scene = this.scene;
        var reset = contArray.oneArray[0];
        var object = params;
        if (object !== undefined)
        {
            var id = object.id;
            var flag = contArray.id.indexOf(id);
            if ( flag==-1 )
            {
                var oldColor = object.material.color;
                if(reset!==undefined){
                    reset.material.color = contArray.oneOldColor[0];
                    contArray.oneArray = [];
                    contArray.oneOldColor = [];
                    contArray.id = [];
                    var borders = scene.getChildByName("borders");
                    scene.remove(borders);
                }
                contArray.id.push(id);
                contArray.oneArray.push(object);
                contArray.oneOldColor.push(oldColor);
                object.material.color = new THREE.Color(0xff0b36);
                this.addBorder(object,0xffff00);
                this.temporary = object;                 //用于交互操作
            }
        }
        else{
            this.removeHit(reset,contArray,scene);
        }
    };
    
    //移除选中状态
    World.prototype.removeHit = function(reset,contArray,scene) {
        if (reset !== undefined) {
            reset.material.color = contArray.oneOldColor[0];
            contArray.oneArray = [];
            contArray.oneOldColor = [];
            contArray.id = [];
            var borders = scene.getChildByName("borders");
            scene.remove(borders);
        }
    };
    
    //屏幕截图保存
    World.prototype.screenShot = function(callback,value,time){
            var scope = this;
            var vaules = value || 0.3;
            var times = time || 5;
            this.canvas = true;
            // if(this.canvas){
            //     var png = scope.canvasRenderer.domElement.toDataURL("image/png",vaules);
            //     scope.canvas = false;
            //     scope.webgl = true;
            //     callback(png);
            // }
            setTimeout(function(){
               var png = scope.canvasRenderer.domElement.toDataURL("image/png",vaules);
                    scope.canvas = false;
                    scope.webgl = true;
                callback(png);
            },times);
    };
    
    //渲染窗口
    World.prototype.render = function(){
            this.update();
    };
    
    
    return World;
});
